﻿using System.Linq;
using System.Text.RegularExpressions;
using System;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Base.Service;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.DataAccess.Common;
using T.FAS.Runtime.DataAccess.Engine.ValidateChecker.Entity;
using T.FAS.Runtime.DataAccess.Engine.ValidateChecker;

namespace T.FAS.Runtime.DataAccess.Engine
{
    public class CommonFactory : IValidaterFactory
    {
        public virtual IColumnValidater GetNullValidater()
        {
            return new CommonNullValidater();
        }

        public virtual IColumnValidater GetDataTypeValidater()
        {
            return new CommonDataTypeValidater();
        }

        public virtual IColumnValidater GetLengthValidater()
        {
            return new CommonLengthValidater();
        }

        public virtual IColumnValidater GetPrecisionValidater()
        {
            return new CommonPrecisionValidater();
        }

        public virtual IColumnValidater GetValidateRuleValidater()
        {
            return new CommonValidateRuleValidater();
        }
    }

    /// <summary>
    /// 通用非空校验Checker
    /// </summary>
    public class CommonNullValidater : IColumnNullValidater
    {
        public ValidateCheckItem Validate(ValidateCheckItem item)
        {
            if (item.Result.IsStop)
                return item;
            //为空验证
            if (item.InputValue == null || string.IsNullOrEmpty(item.InputValue.ToString()))
            {
                if (item.CheckElement.IsAllowNull)
                    item.Result.IsStop = true;  //如果允许为空且输入值为空，停止后续校验
                //如果存在默认值，则通过非空校验，继续后面的校验流
                //todo:是否需要在此进行后端默认值赋值
                else if (!string.IsNullOrEmpty(item.CheckElement.DefaultValue))
                    ;
                else
                {
                    item.Result.Flag = false;
                    item.Result.IsStop = true;
                    item.Result.Msg.Append(string.Format(ValidateConst.NullErrorTemp,
                        item.CheckElement.Name,
                        item.CheckElement.DataType));
                }
            }
            return item;
        }
    }

    /// <summary>
    /// 通用长度校验Checker
    /// </summary>
    public class CommonLengthValidater : IColumnLengthValidater
    {
        public ValidateCheckItem Validate(ValidateCheckItem item)
        {
            if (item.Result.IsStop)
                return item;

            //长度验证
            int length = item.InputValue.ToString().Length;
            if (item.CheckElement.Length < length)
            {
                item.Result.Flag = false;
                item.Result.Msg.Append(string.Format(ValidateConst.LengthErrorTemp,
                    item.CheckElement.Name,
                    item.CheckElement.DataType,
                    item.InputValue,
                    length,
                    item.CheckElement.Length));
            }
            return item;
        }
    }

    /// <summary>
    /// 通用精度校验Checker
    /// </summary>
    public class CommonPrecisionValidater : IColumnPrecisionValidater
    {
        /// <summary>
        /// 需个性化设置，通用checker默认通过校验
        /// </summary>
        /// <param name="item"></param>
        /// <param name="inputValue"></param>
        /// <returns></returns>
        public ValidateCheckItem Validate(ValidateCheckItem item)
        {
            return item;
        }
    }

    /// <summary>
    /// 通用数据类型校验Checker
    /// </summary>
    public class CommonDataTypeValidater : IColumnDataTypeValidater
    {
        /// <summary>
        /// 需个性化设置，通用checker默认通过校验
        /// </summary>
        /// <param name="item"></param>
        /// <param name="inputValue"></param>
        /// <returns></returns>
        public ValidateCheckItem Validate(ValidateCheckItem item)
        {
            if (item.Result.IsStop)
                return item;
            item.ConvertValue = item.InputValue;
            return item;
        }
    }

    /// <summary>
    /// 通用数据类型校验Checker
    /// </summary>
    public class CommonValidateRuleValidater : IValidateRuleValidater
    {
        private static readonly DataType[] s_notCheckBound = new DataType[] {
            DataType.Record,
            DataType.List,
            DataType.Boolean,
            DataType.Binary,
            DataType.String
        };

        /// <summary>
        /// 需个性化设置，通用checker默认通过校验
        /// </summary>
        /// <param name="item"></param>
        /// <param name="inputValue"></param>
        /// <returns></returns>
        public ValidateCheckItem Validate(ValidateCheckItem item)
        {
            if (item.Result.IsStop)
                return item;

            if (item.CheckElement.ValidateRule == null)
                return item;
            else
            {
                string inputValStr = item.InputValue?.ToString();
                try
                {
                    //从sdk中实时获取最新的校验规则（包含自定义校验规则）
                    ValidateRule normalValidateRule = null;
                    DataColumnValidateRule validateRule = item.CheckElement.ValidateRule;
                    if (validateRule == null) return item;
                    if (!string.IsNullOrEmpty(validateRule.NormalValidateRuleID))
                    {
                        //系统规则通过SDK获取，其他从DO列缓存里拿
                        if (validateRule.NormalValidateRuleType == ValidateRuleType.System)
                            normalValidateRule = validateRule.NormalValidateRule = FASValidateRuleRTPClientProxy.GetInstance().GetRule(item.CheckElement.ValidateRule.NormalValidateRuleID);
                        else
                            normalValidateRule = validateRule.NormalValidateRule;
                    }
                    if (normalValidateRule != null)
                    {
                        if (!string.IsNullOrEmpty(inputValStr))
                        {
                            string regRule = string.IsNullOrEmpty(normalValidateRule.CustomRegContent) ? normalValidateRule.OriginRegContent : normalValidateRule.CustomRegContent;
                            if (!string.IsNullOrEmpty(regRule))
                            {
                                if (!Regex.IsMatch(inputValStr, regRule))
                                {
                                    item.Result.Flag = false;
                                    item.Result.Msg.Append(string.Format(ValidateConst.ValidateRuleErrorTemp,
                                        item.CheckElement.Name,
                                        item.CheckElement.DataType,
                                        item.InputValue,
                                        string.IsNullOrEmpty(normalValidateRule.CustomErrMsg) ? normalValidateRule.ErrMsg : normalValidateRule.CustomErrMsg
                                        ));
                                }
                            }
                        }
                    }
                    //可以校验范围规则
                    if (!s_notCheckBound.Contains(item.CheckElement.DataType))
                    {
                        IValidAndConvertToObject typeConverter = DataTypeToolFactory.ValidAndConvertToObject(item.CheckElement.DataType);
                        ICompare typeComparer = DataTypeToolFactory.GetCompare(item.CheckElement.DataType);
                        if (typeConverter != null && typeComparer != null && item.ConvertValue != null)
                        {
                            object lowerBoundVal = null; object upperBoundVal = null;
                            if (!string.IsNullOrEmpty(validateRule.LowerBoundValidate))
                            {
                                try
                                {
                                    lowerBoundVal = typeConverter.ValidAndConvertToObject(validateRule.LowerBoundValidate, false);
                                }
                                catch (Exception e)
                                {
                                }
                            }
                            if (!string.IsNullOrEmpty(validateRule.UpperBoundValidate))
                            {
                                try
                                {
                                    upperBoundVal = typeConverter.ValidAndConvertToObject(validateRule.UpperBoundValidate, false);
                                }
                                catch (Exception e)
                                {
                                }
                            }
                            if (lowerBoundVal != null)
                            {
                                //输入值要大于下界
                                if (!typeComparer.QuantitativeCompare(item.ConvertValue, lowerBoundVal))
                                {
                                    item.Result.Flag = false;
                                    item.Result.IsStop = true;
                                    item.Result.Msg.Append(
                                        string.Format(ValidateConst.LowerBoundValidateErrorTemp,
                                            item.CheckElement.Name, item.CheckElement.DataType, item.InputValue, validateRule.LowerBoundValidate));
                                }
                                //输入值要小于上界
                                if (!typeComparer.QuantitativeCompare(upperBoundVal, item.ConvertValue))
                                {
                                    item.Result.Flag = false;
                                    item.Result.IsStop = true;
                                    item.Result.Msg.Append(
                                        string.Format(ValidateConst.UpperBoundValidateErrorTemp,
                                            item.CheckElement.Name, item.CheckElement.DataType, item.InputValue, validateRule.UpperBoundValidate));

                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    DACLogFactory.GetDACLogService().WriteError(e, $"{item.CheckElement.Name}执行规则校验失败,输入值:{inputValStr}校验失败,msg:{e.Message}");
                }
                return item;
            }
        }
    }
}
